package annotationService.application;


import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import net.sf.json.JSONObject;

import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Directory;
import org.restlet.Restlet;
import org.restlet.Router;
import org.restlet.data.MediaType;
import org.restlet.data.Protocol;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.DomRepresentation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import annotationService.util.JSONSimpler;

/**
 * Restful server serving static files
 * 
 * @author Andres Westermann
 * 
 */
public class ServiceApplication {
	private static VGIPersistenceManager TitlePM = new VGIPersistenceManager("subject");
	private static VGIPersistenceManager AnnotationPM = new VGIPersistenceManager("savedAnnotations");
	static Logger log=Logger.getLogger(ServiceApplication.class.getSimpleName());
	public static void main(String[] argv) throws Exception {
		Component component = new Component();
		component.getServers().add(Protocol.HTTP, 80);
		component.getClients().add(Protocol.FILE);
		Application application = new Application(component.getContext()) {
			
			@Override
			public Restlet createRoot() {
				final String DIR_ROOT_URI="file:///C:/annotationService/";
				Router router = new Router(getContext());
				
				Directory mainDir = new Directory(getContext(), DIR_ROOT_URI);
				Directory publishDir = new Directory(getContext(), DIR_ROOT_URI+"publish/");
				Directory searchDir = new Directory(getContext(), DIR_ROOT_URI+"search/");
				
				publishDir.setListingAllowed(true);
				publishDir.setDeeplyAccessible(true);
				publishDir.setNegotiateContent(true);
				router.attach("", mainDir);
				router.attach("/publish/", publishDir);
				router.attach("/search/", searchDir);
				

				router.attach("/restful/service", VGIResource.class);
				router.attach("/restful/xml", KMLResource.class);

				/* 
				 * Create the account handler
				 * Creates XML representation for title search
				 * Applicable via http://localhost:8182/vgi/title/
				*/
				final Restlet titleSearch = new Restlet() {
					@SuppressWarnings("unchecked")
					@Override
					public void handle(Request request, Response response) {
						// Print the requested URI path
						VGI currentVGI = new VGI();
						String titleString = request.getAttributes().get("title").toString();
						//change backspace in HTML-Link
						if(titleString.contains("%20")){
							titleString = titleString.replace( "%20", " " );
						}
						currentVGI.setSubject(titleString);
						List queryRet = TitlePM.query(currentVGI);
						
						if(queryRet==null){ //not found any VGI Object with the specific title ("titleString")
							try {
								DomRepresentation representation = new DomRepresentation(
										MediaType.TEXT_XML);
							DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
									.newInstance();
							DocumentBuilder documentBuilder;
							documentBuilder = documentBuilderFactory
									.newDocumentBuilder();
							Document document = documentBuilder.newDocument();
							//add rootElement to XML-Dokument ("document")
							Element rootElement = document.createElement("Document");
							document.appendChild(rootElement);
							representation.setDocument(document);
							response.setEntity(representation);
								
							} catch (IOException e) {
								log.info(e.toString());
							}
							catch (ParserConfigurationException e) {
								log.info(e.toString());
							}
						}
						else{ //found a VGI object with the specific title ("titleString")
						try {
							DomRepresentation representation = new DomRepresentation(
						              MediaType.TEXT_XML);
						      // Generate a DOM document representing the list of
						      // vgi objects.
						      Document d = representation.getDocument();
						      Element r = d.createElement("Document");
						      d.appendChild(r);
						      for (int i=0;i<queryRet.size();i++) {
						    	  JSONObject jsonObject = JSONSimpler.FromBeanToJSON(queryRet.get(i));
						          Element elemVGI = d.createElement("VGI_Object");
						          //add title element
						          Element eltName = d.createElement("Title");
						          eltName.appendChild(d.createTextNode(jsonObject
											.get("subject").toString()));
						          elemVGI.appendChild(eltName);
						          //add description element
						          Element elemDescription = d.createElement("Description");
						          elemDescription.appendChild(d.createTextNode(jsonObject
									.get("content").toString()));
						          elemVGI.appendChild(elemDescription);
						          //add tags element
						          Element elemTags = d.createElement("Tags");
						          elemVGI.appendChild(elemTags);
						          String tagsString = jsonObject.get("tags").toString().substring(1, jsonObject.get("tags").toString().length()-1);
						          String[] segTags = tagsString.split( Pattern.quote( ", " ));
						          //add every tag into a single element ("tag")
						          for(int k=0;k<segTags.length;k++){
						        	  Element elemTag = d.createElement("Tag");
						        	  elemTag.appendChild(d.createTextNode(segTags[k]));
						        	  elemTags.appendChild(elemTag);
						          }
						          //add annotation element
						          Element elemAnnotations = d.createElement("Annotations");
						          elemVGI.appendChild(elemAnnotations);
						          String annotationsString = jsonObject.get("savedAnnotations").toString().substring(1, jsonObject.get("savedAnnotations").toString().length()-1);
						          String[] segAnnotations = annotationsString.split( Pattern.quote( ", " ));
						          for(int k=0;k<segAnnotations.length;k++){
						        	  Element elemAnnotation = d.createElement("Annotation");
						        	  elemAnnotation.appendChild(d.createTextNode(segAnnotations[k]));
						        	  elemAnnotations.appendChild(elemAnnotation);
						          }
						          //add kml-URL element
						          Element elemKMLLink = d.createElement("KML_URL");
						          elemKMLLink.appendChild(d.createTextNode(jsonObject
									.get("kmllink").toString()));
						          elemVGI.appendChild(elemKMLLink);
				                  r.appendChild(elemVGI);
				                }
				                d.normalizeDocument();
				                representation.setDocument(d);
				                // Returns the XML representation of this document.
				                response.setEntity(representation);
							
							
							//repsond the whole XML document to the client
							response.setEntity(representation);
						}  catch (IOException e) {
							log.info(e.toString());
						}
						
						}

					}
				};
				/* 
				 * Create the account handler
				 * Creates XML representation for title search
				 * Applicable via http://localhost:8182/vgi/title/
				*/
				final Restlet annotationSearch = new Restlet() {
					@SuppressWarnings("unchecked")
					@Override
					public void handle(Request request, Response response) {
						// Print the requested URI path
						VGI currentVGI = new VGI();
						String categoryString = request.getAttributes().get("annotation").toString();
						//change backspace in HTML-Link
						if(categoryString.contains("%20")){
							categoryString = categoryString.replace( "%20", " " );
						}
						
						currentVGI.setsavedAnnotations(categoryString);
						List queryRet = AnnotationPM.query(currentVGI);
						if(queryRet==null){ //not found any VGI Object with the specific title ("titleString")
							try {
								DomRepresentation representation = new DomRepresentation(
										MediaType.TEXT_XML);
							DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
									.newInstance();
							DocumentBuilder documentBuilder;
							documentBuilder = documentBuilderFactory
									.newDocumentBuilder();
							Document document = documentBuilder.newDocument();
							//add rootElement to XML-Dokument ("document")
							Element rootElement = document.createElement("Document");
							document.appendChild(rootElement);
							representation.setDocument(document);
							response.setEntity(representation);
								
							} catch (IOException e) {
								log.info(e.toString());
							}
							catch (ParserConfigurationException e) {
								log.info(e.toString());
							}
						}
						else{ //found a VGI object with the specific title ("titleString")
						try {
							DomRepresentation representation = new DomRepresentation(
						              MediaType.TEXT_XML);
						      // Generate a DOM document representing the list of
						      // vgi objects.
						      Document d = representation.getDocument();
						      Element r = d.createElement("Document");
						      d.appendChild(r);
						      for (int i=0;i<queryRet.size();i++) {
						    	  JSONObject jsonObject = JSONSimpler.FromBeanToJSON(queryRet.get(i));
						          Element elemVGI = d.createElement("VGI_Object");
						          //add title element
						          Element eltName = d.createElement("Title");
						          eltName.appendChild(d.createTextNode(jsonObject
											.get("subject").toString()));
						          elemVGI.appendChild(eltName);
						          //add description element
						          Element elemDescription = d.createElement("Description");
						          elemDescription.appendChild(d.createTextNode(jsonObject
									.get("content").toString()));
						          elemVGI.appendChild(elemDescription);
						          //add tags element
						          Element elemTags = d.createElement("Tags");
						          elemVGI.appendChild(elemTags);
						          String tagsString = jsonObject.get("tags").toString().substring(1, jsonObject.get("tags").toString().length()-1);
						          String[] segTags = tagsString.split( Pattern.quote( ", " ));
						          //add every tag into a single element ("tag")
						          for(int k=0;k<segTags.length;k++){
						        	  Element elemTag = d.createElement("Tag");
						        	  elemTag.appendChild(d.createTextNode(segTags[k]));
						        	  elemTags.appendChild(elemTag);
						          }
						          //add annotation element
						          Element elemAnnotations = d.createElement("Annotations");
						          elemVGI.appendChild(elemAnnotations);
						          String annotationsString = jsonObject.get("savedAnnotations").toString().substring(1, jsonObject.get("savedAnnotations").toString().length()-1);
						          String[] segAnnotations = annotationsString.split( Pattern.quote( ", " ));
						          for(int k=0;k<segAnnotations.length;k++){
						        	  Element elemAnnotation = d.createElement("Annotation");
						        	  elemAnnotation.appendChild(d.createTextNode(segAnnotations[k]));
						        	  elemAnnotations.appendChild(elemAnnotation);
						          }
						          //add kml-URL element
						          Element elemKMLLink = d.createElement("KML_URL");
						          elemKMLLink.appendChild(d.createTextNode(jsonObject
									.get("kmllink").toString()));
						          elemVGI.appendChild(elemKMLLink);
				                  r.appendChild(elemVGI);
				                }
				                d.normalizeDocument();
				                representation.setDocument(d);
				                // Returns the XML representation of this document.
				                response.setEntity(representation);
							
							
							//repsond the whole XML document to the client
							response.setEntity(representation);
						}  catch (IOException e) {
							log.info(e.toString());
						}
						
						}

					}
				};
				
				// Attach the handlers to the root router
				router.attach("/search/title/{title}", titleSearch);
				router.attach("/search/annotation/{annotation}",annotationSearch);
				return router;
			}
		};
		application.getTunnelService().setEnabled(true);
		application.getTunnelService().setMethodTunnel(true);
		application.getTunnelService().setMethodParameter("method");
		annotationService.util.RDFIterator.updateGEMETFile();
		component.getDefaultHost().attach(application);
		component.start();
	}
}
